package com.ykdl.member.dictionary;

import java.util.LinkedHashMap;
import java.util.Map.Entry;

import com.alibaba.fastjson.JSONObject;

public class DictionaryCache {
	private static final int MAX_CAPACITY = 1024 * 1024;
	private JSONObject mCurVersion;
	private LRULinkedHashMap<String, DictCache> mName2DataMap = new LRULinkedHashMap<String, DictCache>(
			MAX_CAPACITY);
	private long mCurCacheSize;

	private static DictionaryCache mInstance;

	private DictionaryCache() {

	}

	public static DictionaryCache getInstance() {
		if (mInstance == null) {
			mInstance = new DictionaryCache();
		}
		return mInstance;
	}

	public JSONObject getDictDataByName(String name) {
		if (mName2DataMap.containsKey(name)) {
			return mName2DataMap.get(name).getData();
		} else {
			return null;
		}

	}

	public void putDataToCache(String name, JSONObject obj, long size) {
		DictCache cache = new DictCache();
		cache.setName(name);
		cache.setData(obj);
		cache.setSize(size);
		mCurCacheSize += size;
		mName2DataMap.setCurCacheSize(mCurCacheSize);
		mName2DataMap.put(name, cache);
		Entry<String, DictCache> entry = mName2DataMap.getRemovedEntry();
		if (entry != null) {
			mCurCacheSize -= entry.getValue().getSize();
			mName2DataMap.setRemovedEntry(null);
		}
	}

	public void clearCache() {
		mName2DataMap.clear();
	}

	public JSONObject getCurVersion() {
		return mCurVersion;
	}

	public void setCurVersion(JSONObject obj) {
		mCurVersion = obj;
	}

	private class DictCache {
		private String name;
		private JSONObject data;
		private long size;

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public JSONObject getData() {
			return data;
		}

		public void setData(JSONObject obj) {
			this.data = obj;
		}

		public float getSize() {
			return size;
		}

		public void setSize(long size) {
			this.size = size;
		}
	}

	private class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
		/**
		 * 
		 */
		private static final long serialVersionUID = -7976320918263655158L;
		private static final float DEFAULT_LOAD_FACTOR = 1f;
		private final int mMaxCapacity;
		private long mCurCacheSize;
		private Entry<K, V> mRemovedEntry;
		private Object mLock = new byte[0];

		public LRULinkedHashMap(int maxCapacity) {
			super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
			this.mMaxCapacity = maxCapacity;
		}

		@Override
		protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
			mRemovedEntry = eldest;
			return mCurCacheSize > mMaxCapacity;
		}

		@Override
		public V get(Object key) {
			synchronized (mLock) {
				return super.get(key);
			}
		}

		@Override
		public V put(K key, V value) {
			synchronized (mLock) {
				return super.put(key, value);
			}
		}

		@Override
		public V remove(Object key) {
			synchronized (mLock) {
				return super.remove(key);
			}
		}

		@Override
		public void clear() {
			synchronized (mLock) {
				super.clear();
			}
		}

		public float getCurCacheSize() {
			return mCurCacheSize;
		}

		public void setCurCacheSize(long curCacheSize) {
			this.mCurCacheSize = curCacheSize;
		}

		public Entry<K, V> getRemovedEntry() {
			return this.mRemovedEntry;
		}

		public void setRemovedEntry(Entry<K, V> entry) {
			this.mRemovedEntry = entry;
		}
	}
}
